#include "list.h"

#include "item.h"
#include "source.h"

#include "namespace.h"
#include "uniquename.h"

#include <assert.h>

List::List()
:   QObject()
,   m_nameSpace(new NameSpace())
,   m_name("unnamed")
,   m_sum(-1)
{
}

List::~List()
{
    while(!m_items.isEmpty())
        removeItem(*m_items.begin());

    delete m_nameSpace;
}

NameSpace *List::nameSpace()
{
    return m_nameSpace;
}

const List::t_items &List::items() const
{
    return m_items;
}

void List::setName(const QString &name)
{
    m_name = name;
    emit nameChanged(name);
    emit modified();
}

const QString List::name() const
{
    return m_name;
}

const bool List::sumIsValid() const
{
    return m_sum >= 0;
}

const int List::sum() const
{
    return m_sum;
}

const bool List::addItem(Item *item)
{
    if(m_items.contains(item))
        return false;

    m_items << item;

    connect(item, SIGNAL(modified()), this, SIGNAL(modified()));

    connect(item, SIGNAL(sourceAdded(Source*))
        , this, SLOT(item_sourceAdded(Source*)));
    connect(item, SIGNAL(sourceRemoved(Source*))
        , this, SLOT(item_sourceRemoved(Source*)));

    connect(item, SIGNAL(ignoreStateChanged(bool))
        , this, SLOT(item_ignoreStateChanged(bool)));
    connect(item, SIGNAL(sourceIgnoreStateChanged(bool))
        , this, SLOT(item_sourceIgnoreStateChanged(bool)));


    connect(item, SIGNAL(updated(uint, uint))
        , this, SLOT(item_updated(uint, uint)));

    emit itemAdded(item);
    emit modified();

    foreach(Source *source, item->sources())
        item_sourceAdded(source);

    return true;
}

const bool List::removeItem(Item *item)
{
    if(!m_items.contains(item))
        return false;

    m_items.remove(m_items.indexOf(item));
    delete item;

    emit itemRemoved(item);
    emit modified();

    return true;
}

void List::item_sourceAdded(Source *source)
{
    emit numSourcesChanged(numSources());
}

void List::item_sourceRemoved(Source *source)
{
    emit numSourcesChanged(numSources());
}

void List::item_ignoreStateChanged(bool ignored)
{
}

void List::item_sourceIgnoreStateChanged(bool ignored)
{
}




void List::update()
{
    if(isUpdating())
        return;

    m_succeeded = 0;
    m_failed = 0;

    foreach(Item *item, m_items)
        item->update();
}

void List::cancel()
{
    if(!isUpdating())
        return;

    foreach(Item *item, m_items)
        item->cancel();
}

void List::item_updated(
    uint succeeded
,   uint failed)
{
    m_succeeded += succeeded;
    m_failed += failed;

    if(isUpdating())
        return;

    uint skipped = numSources() - m_failed - m_succeeded;
    emit updated(m_succeeded, m_failed, skipped);
}

const bool List::isUpdating() const
{
    foreach(Item *item, m_items)
        if(item->isUpdating())
            return true;

    return false;
}

const uint List::numSources() const
{
    uint num = 0;

    foreach(Item *item, m_items)
        num += item->sources().size();

    return num;
}
